//
//  ZYANRMonitor.m
//  OC_Principle
//
//  Created by wangzhipan on 2025/2/12.
//

#import "ZYANRMonitor.h"

@interface ZYANRMonitor() {
    dispatch_semaphore_t _semaphore;
    CFRunLoopObserverRef _observerRef;
    NSUInteger _count;
    CFRunLoopActivity _activity;
}

//线程安全问题
@property (atomic, assign) BOOL isMonitoring;
@end

@implementation ZYANRMonitor
+ (instancetype)sharedInstance
{
    static id _instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

- (instancetype)init
{
    if (self = [super init]) {
        self.isMonitoring = NO;
        _count = 0;
    }
    return self;
}

- (void)startMonitoring
{
    if (self.isMonitoring) {
        return;
    }
    self.isMonitoring = YES;
    
    [self registerObserver];
}

- (void)stop
{
    if (!self.isMonitoring) {
        return;
    }
    
    self.isMonitoring = NO;
    CFRunLoopRemoveObserver(CFRunLoopGetMain(), _observerRef, kCFRunLoopCommonModes);
    CFRelease(_observerRef);
    _observerRef = nil;
    _semaphore = nil;
}

- (void)registerObserver
{
    _semaphore = dispatch_semaphore_create(0);
    _observerRef = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        [self runloopObserver:observer activity:activity];
    });
    CFRunLoopAddObserver(CFRunLoopGetMain(), _observerRef, kCFRunLoopCommonModes);
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        while (self.isMonitoring) {
            //当没有超时时，result==0， 50ms监控
            intptr_t result = dispatch_semaphore_wait(self->_semaphore, dispatch_time(DISPATCH_TIME_NOW, 50.0 / 1000  * NSEC_PER_SEC));
            if (result != 0) {
                if (self->_activity == kCFRunLoopBeforeSources) {
                    /*此时主线程正准备处理 Source0 事件
                      如果卡顿，可能是：
                             1. UI 刷新任务过重
                             2. 用户事件处理耗时
                             3. 其他同步任务阻塞
                     */
                    self->_count++;
                }
                else if (self->_activity == kCFRunLoopAfterWaiting) {
                    /* 此时主线程刚被唤醒
                       如果卡顿，可能是：
                              1. 大量事件待处理
                              2. 某个事件处理时间过长
                              3. 线程间锁竞争
                     */
                    
                    self->_count++;
                }
                else {
                    /* 其他状态不计入卡顿统计
                          因为这些状态要么是正常的等待（BeforeWaiting）
                          要么是 RunLoop 状态切换（Entry/Exit）
                     */
                    self->_count = 0;
                }
                
                if (self->_count < 5) {
                    continue;
                }
                [self logBacktrace];
            }
            self->_count = 0;
        }
    });
}

- (void)runloopObserver:(CFRunLoopObserverRef)observer
               activity:(CFRunLoopActivity)activity
{
    _activity = activity;
    dispatch_semaphore_signal(_semaphore);
}

- (void)logBacktrace
{
    //打印堆栈
}
@end
